package com.yance.fim.websocket;

import com.yance.fim.core.enums.Code;
import com.yance.fim.core.enums.Command;
import com.yance.fim.core.handler.codec.WsMessageHandler;
import com.yance.fim.core.packets.FimHeader;
import com.yance.fim.core.packets.FimPacket;
import com.yance.fim.core.packets.dto.WebSocketMainMessage;
import com.yance.fim.handler.MessageHandlerDispatcher;
import com.yance.fim.utils.Constants;
import io.netty.util.internal.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.tio.core.ChannelContext;
import org.tio.http.common.HttpRequest;
import org.tio.http.common.HttpResponse;
import org.tio.utils.json.Json;
import org.tio.websocket.common.WsRequest;
import org.tio.websocket.common.WsSessionContext;
import org.tio.websocket.server.handler.IWsMsgHandler;

import java.util.Objects;

/**
 * @author yance
 */
@Service
public class FimWsMsgHandler implements IWsMsgHandler {

    private static Logger log = LoggerFactory.getLogger(FimWsMsgHandler.class);

    private final MessageHandlerDispatcher messageHandlerDispatcher;

    public FimWsMsgHandler(MessageHandlerDispatcher messageHandlerDispatcher) {
        this.messageHandlerDispatcher = messageHandlerDispatcher;
    }

    /**
     * 握手时走这个方法，业务可以在这里获取cookie，request参数等
     *
     * @param request
     * @param httpResponse
     * @param channelContext
     * @return
     */
    @Override
    public HttpResponse handshake(HttpRequest request, HttpResponse httpResponse, ChannelContext channelContext) {
        String clientip = request.getClientIp();
        log.info("收到来自{}的ws握手包\r\n{}", clientip, request.toString());
        return httpResponse;
    }

    /**
     * 握手后走这个方法
     *
     * @param httpRequest
     * @param httpResponse
     * @param channelContext
     */
    @Override
    public void onAfterHandshaked(HttpRequest httpRequest, HttpResponse httpResponse, ChannelContext channelContext) {

    }

    /**
     * 字节消息（binaryType = arraybuffer）过来后会走这个方法
     *
     * @param wsRequest
     * @param bytes
     * @param channelContext
     * @return
     */
    @Override
    public Object onBytes(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) {
        return null;
    }

    /**
     * 当客户端发close flag时，会走这个方法
     *
     * @param wsRequest
     * @param bytes
     * @param channelContext
     * @return
     */
    @Override
    public Object onClose(WsRequest wsRequest, byte[] bytes, ChannelContext channelContext) {
        return null;
    }

    /**
     * 字符消息（binaryType = blob）过来后会走这个方法
     *
     * @param wsRequest
     * @param message
     * @param channelContext
     * @return
     */
    @Override
    public Object onText(WsRequest wsRequest, String message, ChannelContext channelContext) {
        WsSessionContext wsSessionContext = (WsSessionContext) channelContext.get();
        //获取websocket握手包
        HttpRequest httpRequest = wsSessionContext.getHandshakeRequest();
        //获取客户端Ip
        String clientIp = httpRequest.getClientIp();
        //收到客户端心跳包
        if (Objects.equals(Constants.TEXT_KEY_HEARTBEAT, message)) {
            return null;
        }
        log.warn("收到客户端 IP为:{},消息为:{}", clientIp, message);
        //接收到web端发送的消息
        if (!StringUtil.isNullOrEmpty(message)) {
            try {
                WebSocketMainMessage webSocketMainMessage = Json.toBean(message, WebSocketMainMessage.class);
                if (webSocketMainMessage != null) {
                    messageHandlerDispatcher.dispatchers(convertFimPacket(webSocketMainMessage), channelContext);
                }
            } catch (Exception e) {
                e.printStackTrace();
                log.error("MessageHandlerDispatcher Exception ! ");
            }
        }
        //返回值是要发送给客户端的内容，一般都是返回null
        return null;
    }

    private FimPacket convertFimPacket(WebSocketMainMessage webSocketMainMessage){
        FimPacket pushPacket = new FimPacket();
        FimHeader header = new FimHeader();
        header.setCommand(Command.toEnum(webSocketMainMessage.getCommand()));
        header.setCode(Code.toEnum(webSocketMainMessage.getCode()));
        header.setMessageId(webSocketMainMessage.getMessageId());
        int length = webSocketMainMessage.getContent() != null ? webSocketMainMessage.getContent().getBytes().length : 0;
        header.setLength(length);
        pushPacket.setHeader(header);
        if(length != 0){
            pushPacket.setBody(WsMessageHandler.getInstance().handleRequest(header.getCommand(),header.getCode(),webSocketMainMessage.getContent()));
        }
        return pushPacket;
    }
}
